package com.cctv.video.api;

import com.cctv.video.network.BaseContent;
import com.cctv.video.network.LogUtil;
import com.cctv.video.network.file.ProgressResponseBody;
import com.cctv.video.network.gson.DoubleDefaultAdapter;
import com.cctv.video.network.gson.IntegerDefaultAdapter;
import com.cctv.video.network.gson.LongDefaultAdapter;
import com.cctv.video.network.gson.StringNullAdapter;
import com.cctv.video.network.mvp.BaseView;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import okhttp3.*;
import okio.Buffer;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
import retrofit2.converter.gson.GsonConverterFactory;

import java.io.IOException;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

import static java.nio.charset.StandardCharsets.UTF_8;

/**
 * 作者：created by LP_TREAM on 2020/11/26 19:41
 * 邮箱：806875201@qq.com
 */
public class ApiRetrofit {
    //是否打开规范模式  解决服务器返回不规范问题
    private Boolean isOpenSpecs = false;

    private String TAG = "ApiRetrofit %s";
    private static Retrofit retrofit;

    private Gson gson;
    private static final int DEFAULT_TIMEOUT = 135;

    private static List<Retrofit> mRetrofitList = new ArrayList<>();

    public static String mBaseUrl = BaseContent.getBaseUrl();

    private static BaseView mBaseView = null;

    private static volatile Type mType = Type.BASE;

    public enum Type {
        FILE,
        BASE,
        BASE_URL,
    }

    public Type getType() {
        return mType;
    }

    public static void setType(Type type) {
        mType = type;
    }

    /**
     * 文件处理
     *
     * @param httpClientBuilder
     */
    public void initFileClient(OkHttpClient.Builder httpClientBuilder) {
        /**
         * 处理文件下载进度展示所需
         */
        httpClientBuilder.addNetworkInterceptor(new ProgressInterceptor());
    }

    /**
     * 默认所需
     *
     * @param httpClientBuilder
     */
    public void initDefaultClient(OkHttpClient.Builder httpClientBuilder) {
        /**
         * 处理一些识别识别不了 ipv6手机，如小米  实现方案  将ipv6与ipv4置换位置，首先用ipv4解析
         */
//        httpClientBuilder.dns(new ApiDns());

        /**
         * 添加cookie管理
         * 方法1：第三方框架
         */
//        PersistentCookieJar cookieJar = new PersistentCookieJar(new SetCookieCache(),
//                new SharedPrefsCookiePersistor(BaseApp.getContent()));
//        httpClientBuilder.cookieJar(cookieJar);

        /**
         * 添加cookie管理
         * 方法2：手动封装cookie管理
         */
//        httpClientBuilder.cookieJar(new CookieManger(BaseApp.getContent()));

        /**
         * 添加日志拦截 实现方式1     上下俩种二者选其一即可
         */
//        httpClientBuilder.addInterceptor(new JournalInterceptor());

        /**
         * 添加日志拦截 实现方式2     上下俩种二者选其一即可
         */
//        HttpLoggingInterceptor logInterceptor = new HttpLoggingInterceptor(new HttpLogger());
//        logInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
//        httpClientBuilder.addInterceptor(logInterceptor);

        /**
         * 添加请求头
         */
        httpClientBuilder.addInterceptor(new HeadUrlInterceptor());

        /**
         * 忽略证书
         */
//        httpClientBuilder.hostnameVerifier(new AllowAllHostnameVerifier());
    }

    public ApiRetrofit() {
        OkHttpClient.Builder httpClientBuilder = new OkHttpClient.Builder();
        httpClientBuilder
                .connectTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS)
                .writeTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS)
                .readTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS)
                .retryOnConnectionFailure(true);//错误重联

        switch (getType()) {
            case FILE:
                initFileClient(httpClientBuilder);
                break;
            case BASE:
            case BASE_URL:
                initDefaultClient(httpClientBuilder);
                break;
        }

        if (isOpenSpecs) {
            retrofit = new Retrofit.Builder()
                    .baseUrl(mBaseUrl)
                    .addConverterFactory(GsonConverterFactory.create(buildGson()))
                    .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                    .client(httpClientBuilder.build())
                    .build();
        } else {
            retrofit = new Retrofit.Builder()
                    .baseUrl(mBaseUrl)
                    .addConverterFactory(GsonConverterFactory.create(buildGson()))
                    .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                    .client(httpClientBuilder.build())
                    .build();
        }
        mRetrofitList.add(retrofit);
    }


    /**
     * 增加后台返回""和"null"的处理,如果后台返回格式正常
     * 1.int=>0
     * 2.double=>0.00
     * 3.long=>0L
     * 4.String=>""
     *
     * @return
     */
    public Gson buildGson() {
        if (gson == null) {
            gson = new GsonBuilder()
                    .registerTypeAdapter(Integer.class, new IntegerDefaultAdapter())
                    .registerTypeAdapter(int.class, new IntegerDefaultAdapter())
                    .registerTypeAdapter(Double.class, new DoubleDefaultAdapter())
                    .registerTypeAdapter(double.class, new DoubleDefaultAdapter())
                    .registerTypeAdapter(Long.class, new LongDefaultAdapter())
                    .registerTypeAdapter(long.class, new LongDefaultAdapter())
                    .registerTypeAdapter(String.class, new StringNullAdapter())
                    .create();
        }
        return gson;
    }


    private static <T> T create(Class<T> cls, String baseUrl) {
        mBaseUrl = baseUrl;
        if (retrofit == null) {
            new ApiRetrofit();
        } else {
            initRetrofit();
        }
        T t = retrofit.create(cls);
        return t;
    }

    private static void initRetrofit() {
        int mIndex = -1;
        for (int i = 0; i < mRetrofitList.size(); i++) {
            if (mBaseUrl.equals(mRetrofitList.get(i).baseUrl().toString())) {
                mIndex = i;
                break;
            }
        }
        //新的baseUrl
        if (mIndex == -1) {
            synchronized (Object.class) {
                new ApiRetrofit();
            }
        } else {
            //已经创建过的baseUrl
            retrofit = mRetrofitList.get(mIndex);
        }
    }

    /**
     * 默认使用方式
     *
     * @return
     */
    public static <T> T getInstance(Class<T> cls) {
        setType(Type.BASE);
        mBaseView = null;

        return create(cls, BaseContent.getBaseUrl());
    }

    /**
     * 文件下载使用方式
     *
     * @param baseView
     * @return
     */
    public static <T> T getFileInstance(Class<T> cls, BaseView baseView) {
        setType(Type.FILE);
        mBaseView = baseView;

        return create(cls, BaseContent.getBaseUrl() + "file/");
    }

    /**
     * 动态改变baseUrl使用方式
     *
     * @param baseUrl
     * @return
     */
    public static <T> T getBaseUrlInstance(Class<T> cls, String baseUrl) {
        setType(Type.BASE_URL);
        mBaseView = null;

        return create(cls, baseUrl);
    }


    /**
     * 请求访问quest    打印日志
     * response拦截器
     */
    public class JournalInterceptor implements Interceptor {
        @Override
        public Response intercept(Chain chain) throws IOException {
            Request request = chain.request();
            try {
                long startTime = System.currentTimeMillis();
                Response response = chain.proceed(request);
                if (response == null) {
                    return chain.proceed(request);
                }
                long endTime = System.currentTimeMillis();
                long duration = endTime - startTime;
                MediaType mediaType = response.body().contentType();
                String content = response.body().string();
//                printParams(request.body());
                LogUtil.e("----------Request Start----------------");
                LogUtil.e("| " + request.toString() + "===========" + request.headers().toString());
                LogUtil.e(content);
//                Logger.e(content);
                LogUtil.e("----------Request End:" + duration + "毫秒----------");

                return response.newBuilder()
                        .body(ResponseBody.create(mediaType, content))
                        .build();
            } catch (Exception e) {
                e.printStackTrace();
                return chain.proceed(request);
            }
        }
    }

    /**
     * 请求参数日志打印
     *
     * @param body
     */
    private void printParams(RequestBody body) {
        if (body != null) {
            Buffer buffer = new Buffer();
            try {
                body.writeTo(buffer);
                Charset charset = Charset.forName("UTF-8");
                MediaType contentType = body.contentType();
                if (contentType != null) {
                    charset = contentType.charset(UTF_8);
                }
                String params = buffer.readString(charset);
                LogUtil.e( "请求参数： | " + params);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }


    /**
     * 添加  请求头
     */
    public class HeadUrlInterceptor implements Interceptor {
        @Override
        public Response intercept(Chain chain) throws IOException {
            Request request = chain.request()
                    .newBuilder()
//                    .addHeader("Content-Type", "text/html; charset=UTF-8")
//                    .addHeader("Vary", "Accept-Encoding")
//                    .addHeader("Server", "Apache")
//                    .addHeader("Pragma", "no-cache")
                    .addHeader("Connection", "close")
                    .addHeader("verification_code", "1.0.0")
                    .addHeader("token", "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwaG9uZW51bWJlciI6IjEzNTQ2NDU0NTY3IiwiZXhwIjoxNjA2MzU3MDIwfQ.c8yhFpG6JsNtaYKXna8P1JXuYocvuLjUVDrhxFwvAuw")
                    .build();
            return chain.proceed(request);
        }
    }

    /**
     * 文件下载进度拦截
     */
    public class ProgressInterceptor implements Interceptor {
        @Override
        public Response intercept(Chain chain) throws IOException {
            Request request = chain.request();
            if (mBaseView != null) {
                Response response = chain.proceed(request);
                return response.newBuilder().body(new ProgressResponseBody(response.body(),
                        new ProgressResponseBody.ProgressListener() {
                            @Override
                            public void onProgress(long totalSize, long downSize) {
                                int progress = (int) (downSize * 100 / totalSize);
                                if (mBaseView != null) {
                                    LogUtil.e("文件操作速度 === " + progress);
                                    mBaseView.onProgress(progress);
                                }
                            }
                        })).build();
            } else {
                return chain.proceed(request);
            }
        }
    }

    /**
     * 获得HTTP 缓存的拦截器
     *
     * @return
     */
    /*public class HttpCacheInterceptor implements Interceptor {
        @Override
        public Response intercept(Chain chain) throws IOException {
            Request request = chain.request();
            // 无网络时，始终使用本地Cache
            if (!NetWorkUtils.isConnected()) {
                request = request.newBuilder()
                        .cacheControl(CacheControl.FORCE_CACHE)
                        .build();
            }
            Response response = chain.proceed(request);
            if (NetWorkUtils.isConnected()) {
                //有网的时候读接口上的@Headers里的配置，你可以在这里进行统一的设置
                String cacheControl = request.cacheControl().toString();
                return response.newBuilder()
                        .header("Cache-Control", cacheControl)
                        .removeHeader("Pragma")
                        .build();
            } else {
                // 无网络时，设置超时为4周
                int maxStale = 60 * 60 * 24 * 28;
                return response.newBuilder()
                        //这里的设置的是我们的没有网络的缓存时间，想设置多少就是多少。
                        .header("Cache-Control", "public, only-if-cached, max-stale=" + maxStale)
                        .removeHeader("Pragma")
                        .build();
            }
        }
    }*/


}

